OpenRoads Designer CONNECT Edition SDK Help

Track cursor

Description

  • This is a custom interactive tool that tracks cursor over an alignment.

  • The user needs to select an alignment and hover over it to track cursor.

  • This code only generates data which has shown in above image, user needs to add the form to show the data.

  • The TrackCursor class which extends DgnElementSetTool which handles different events to interact with UI, the TrackCursor class overrides the events here in this tool .

Remarks

  • This sample code is a part of ManagedSDKExample which you get with SDK installation under "examples" section in SDK installation directory.

  • If you encounter any error while using DgnElementSetTool class, make sure to add a reference to Bentley.DgnDisplayNet.dll by selecting Project > Add Reference or change the projects .csproj file to add reference to this dll .

  • The default dll location will be "C:\Program Files\Bentley\OpenRoads Designer CE 10.11\OpenRoadsDesigner\Bentley.DgnDisplayNet.dll"

  • The method OnDataButton() handles the code for alignment selection.

Source Code



//Required References
using System;
using System.Windows.Forms;
using System.Collections.Generic;
using Bentley.DgnPlatformNET;
using Bentley.DgnPlatformNET.Elements;
using Bentley.GeoCoordinatesNET;
using Bentley.GeometryNET;
using Bentley.MstnPlatformNET;
using Bentley.CifNET.SDK.Edit;
using Bentley.CifNET.GeometryModel.SDK;
using Bentley.CifNET.LinearGeometry;
using Bentley.CifNET.Formatting;


namespace ManagedSDKExample.Examples
{
  
        public enum CommandState
        {
            PickAlignment = 0,
            TrackCursor,
        }

        /// <summary>
        /// Track Cursor
        /// Tracks cursor dynamically
        /// </summary>
        /// <author>Joseph.Ashe</author>                   <date>07/2019</date>
        class TrackCursor : DgnElementSetTool
        {

            #region Members

            private BaseGCS ProjectionGCS { get; set; } = null;
            private DgnGCS ModelGCS { get; set; } = null;
            private ConsensusConnectionEdit Connection { get; set; } = null;
            private CommandState State { get; set; } = CommandState.PickAlignment;
            private Alignment SelectedAlignment { get; set; } = null;
            private bool SkippedAlignment { get; set; } = false;
            private TerrainSurface SelectedTerrain { get; set; } = null;
            private List<DataPoint> DataPoints { get; set; } = new List<DataPoint>();

            #endregion

            #region Tool Overrides

            protected override void OnPostInstall()
            {
                this.ModelGCS = DgnGCS.FromModel(Session.Instance.GetActiveDgnModelRef(), true);
                if (this.ModelGCS != null)
                    this.ProjectionGCS = this.ModelGCS;
                else
                    this.ProjectionGCS = this.LaunchBaseSelectorForm("Select a Projection System");

                Bentley.DgnPlatformNET.AccuSnap.LocateEnabled = true;
                Bentley.DgnPlatformNET.AccuSnap.SnapEnabled = true;

                this.Connection = Bentley.CifNET.SDK.Edit.ConsensusConnectionEdit.GetActive();
                GeometricModel geomModel = Connection.GetActiveGeometricModel();
                if (geomModel != null)
                {
                    SurfaceEntity activeSurface = geomModel.ActiveSurface;
                    if (activeSurface != null && activeSurface is TerrainSurface)
                        this.SelectedTerrain = activeSurface as TerrainSurface;
                }

             
                this.SetupAndPromptForNextAction();
            }

            protected override void OnCleanup()
            {
              
                if (this.ProjectionGCS != null)
                    this.ProjectionGCS.Dispose();
                if (this.ModelGCS != null)
                    this.ModelGCS.Dispose();
            }

            protected override void SetupAndPromptForNextAction()
            {
                if (this.SelectedAlignment != null || this.SkippedAlignment || this.Connection == null)
                    this.State = CommandState.TrackCursor;

                switch (this.State)
                {
                    case CommandState.PickAlignment:
                        {
                            EndDynamics();
                            SetLocateCriteria();
                            SetLocateCursor(true);
                            BeginPickElements();
                            NotificationManager.OutputPrompt("Select an alignment or reset");
                            break;
                        }
                    case CommandState.TrackCursor:
                        {
                            BeginDynamics();
                            break;
                        }
                }
            }

            //Selects alignment
            protected override bool OnDataButton(Bentley.DgnPlatformNET.DgnButtonEvent ev)
            {
                switch (this.State)
                {
                    case CommandState.PickAlignment:
                        {
                            Bentley.DgnPlatformNET.HitPath hitPath = DoLocate(ev, true, 0);
                            if (hitPath != null)
                            {
                                Element el = hitPath.GetCursorElement();
                                if (el != null)
                                {
                                    Alignment al = (el.ParentElement == null) ? Alignment.CreateFromElement(Connection, el) : Alignment.CreateFromElement(Connection, el.ParentElement);
                                    if (al != null)
                                    {
                                        SelectedAlignment = al;
                                    }
                                }
                            }
                            SetupAndPromptForNextAction();
                            break;
                        }
                    case CommandState.TrackCursor:
                        {
                            DataPoint p = new DataPoint(ev.Point, this.ProjectionGCS, this.SelectedAlignment, this.SelectedTerrain);
                            DataPoints.Add(p);
                            break;
                        }
                }
                return false;
            }

            protected override void OnDynamicFrame(DgnButtonEvent ev)
            {
                
                bool isProjectionValid = this.ProjectionGCS != null;
                bool isAlignmentValid = this.SelectedAlignment != null;
                bool isSurfaceValid = this.SelectedTerrain != null;

                List<string> names = new List<string>();
                List<string> values = new List<string>();

                DataPoint p = new DataPoint(ev.Point, this.ProjectionGCS, this.SelectedAlignment, this.SelectedTerrain);
                p.GetStringLists(ref names, ref values, isProjectionValid, isAlignmentValid, isSurfaceValid, false);
                
                this.DrawGraphics(this.SelectedAlignment, ev);
            }

            private void DrawGraphics(Alignment alignment, DgnButtonEvent uorPoint)
            {
                if (alignment != null)
                {
                    DgnModel model = Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModel();
                    ModelInfo info = model.GetModelInfo();
                    double UORTOMETER = 1.0 / info.UorPerMeter;

                    double x = UORTOMETER * uorPoint.Point.X;
                    double y = UORTOMETER * uorPoint.Point.Y;
                    double z = UORTOMETER * uorPoint.Point.Z;
                    if (!model.Is3d)
                        z = 0;

                    DPoint3d metricPoint = new DPoint3d(x, y, z);
                    double metricZ = z;

                    LinearPoint lp = alignment.LinearGeometry.ProjectPointOnPerpendicular(metricPoint);
                    if (lp != null)
                    {
                        Profile pr = alignment.ActiveProfile;
                        if (pr != null)
                        {
                            LinearPoint pp = pr.ProfileGeometry.GetPointAtX(lp.DistanceAlong);
                            if (pp != null)
                                metricZ = pp.Coordinates.Y;
                        }

                        /// Draw line from projected point to cursor
                        RedrawElems redraw = new RedrawElems();
                        redraw.DrawMode = DgnDrawMode.TempDraw;
                        redraw.DrawPurpose = DrawPurpose.Dynamics;
                        redraw.SetDynamicsViewsFromActiveViewSet(uorPoint.Viewport);

                        List<DPoint3d> points = new List<DPoint3d>();
                        DPoint3d pjp = new DPoint3d(lp.Coordinates.X / UORTOMETER, lp.Coordinates.Y / UORTOMETER, metricZ / UORTOMETER);
                        points.Add(pjp);
                        points.Add(uorPoint.Point);

                        LineStringElement lse = new LineStringElement(model, null, points.ToArray());
                        redraw.DoRedraw(lse);
                    }
                }
            }

            protected override bool OnResetButton(Bentley.DgnPlatformNET.DgnButtonEvent ev)
            {
                switch (this.State)
                {
                    case CommandState.PickAlignment:
                        {
                            this.SkippedAlignment = true;
                            SetupAndPromptForNextAction();
                            return false;
                        }
                    case CommandState.TrackCursor:
                        {
                            if (this.DataPoints.Count > 0)
                            {
                                ReportPoints();
                                this.DataPoints.Clear();
                                return false;
                            }
                            else
                            {
                                ExitTool();
                                return true;
                            }
                        }
                }
                return true;
            }

            protected override void OnRestartTool()
            {
                InstallNewInstance();
            }

            public override StatusInt OnElementModify(Element element)
            {
                return StatusInt.Error;
            }

            public static void InstallNewInstance()
            {
                TrackCursor tool = new TrackCursor();
                tool.InstallTool();
            }

            #endregion

            #region Private Methods

            private BaseGCS LaunchBaseSelectorForm(string title, BaseGCS namedGCS = null)
            {
                BaseSelectorForm form = null;
                try
                {
                    form = new BaseSelectorForm(title, namedGCS, string.Empty);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error Occured", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                if (form != null)
                {
                    DialogResult res = form.ShowDialog();
                    if (res == DialogResult.OK)
                        return form.SelectedGCS;
                }

                if (namedGCS != null)
                    return namedGCS;
                return null;
            }

            #endregion

            #region ReportPoints

            private void ReportPoints()
            {
                if (this.DataPoints.Count == 0)
                    return;
                DgnModel model = Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModel();
                if (model == null) return;

                var sdkCon = Bentley.CifNET.SDK.Edit.ConsensusConnectionEdit.GetActive();
                if (sdkCon == null)
                    return;

                GeometricModel geomModel = sdkCon.GetActiveGeometricModel();
                if (geomModel == null)
                    return;

                DgnModel dgn = geomModel.DgnModel;
                DgnFile file = dgn.GetDgnFile();
                Dictionary<string, string> fileProperties = new Dictionary<string, string>();
                fileProperties.Add("Project", dgn.ModelName);
                fileProperties.Add("File Name", file.GetFileName());
                fileProperties.Add("Last Accessed", file.LastSaveTimeUtc.ToString());

                bool isProjectionValid = this.ProjectionGCS != null;
                bool isAlignmentValid = this.SelectedAlignment != null;
                bool isSurfaceValid = this.SelectedTerrain != null;

                Dictionary<string, string> selectedProperties = new Dictionary<string, string>();

                if (isProjectionValid)
                {
                    selectedProperties.Add("Geographic Projection System", this.ProjectionGCS.Name);
                    selectedProperties.Add(" ", this.ProjectionGCS.Description);
                    selectedProperties.Add("Geographic Projection Ellipsoid", this.ProjectionGCS.EllipsoidName);
                    selectedProperties.Add("  ", this.ProjectionGCS.EllipsoidDescription);
                }

                if (isAlignmentValid)
                {
                    selectedProperties.Add("Alignment Name", this.SelectedAlignment.Name);
                    if (SelectedAlignment.FeatureDefinition != null)
                        selectedProperties.Add("Alignment Feature", this.SelectedAlignment.FeatureDefinition.Name);
                    selectedProperties.Add("Alignment Length", FormatForDisplay.Distance(this.SelectedAlignment.LinearGeometry.Length, model, 3));


                    if (SelectedAlignment.ActiveProfile != null)
                    {
                        string name = (String.IsNullOrWhiteSpace(this.SelectedAlignment.ActiveProfile.Name) ? "Active" : this.SelectedAlignment.ActiveProfile.Name);
                        selectedProperties.Add("Profile Name", name);
                        if (SelectedAlignment.ActiveProfile.FeatureDefinition != null)
                            selectedProperties.Add("Profile Feature", this.SelectedAlignment.ActiveProfile.FeatureDefinition.Name);
                    }
                }

                if (isSurfaceValid)
                {
                    selectedProperties.Add("Surface Name", this.SelectedTerrain.Name);
                    if (this.SelectedTerrain.FeatureDefinition != null)
                        selectedProperties.Add("Surface Feature", this.SelectedTerrain.FeatureDefinition.Name);
                }

                int count = 1;
                List<string> data = new List<string>();
                foreach (var p in this.DataPoints)
                {
                    List<string> names = new List<string>();
                    List<string> values = new List<string>();
                    p.GetStringLists(ref names, ref values, isProjectionValid, isAlignmentValid, isSurfaceValid, true);
                    string row = count.ToString() + "|";
                    foreach (var item in values)
                        row += item + "|";
                    row.Trim('|');
                    data.Add(row);
                    count++;
                }

                List<string> lables = new List<string>();
                List<string> dummy = new List<string>();
                lables.Add("Point");
                this.DataPoints[0].GetStringLists(ref lables, ref dummy, isProjectionValid, isAlignmentValid, isSurfaceValid, true);

            }

            #endregion

        }

        /// <summary>
        /// Data Point
        /// </summary>
        /// <author>Joseph.Ashe</author>                   <date>07/2019</date>
        internal class DataPoint
        {

            #region Members
            public string East { get; set; } = string.Empty;
            public string North { get; set; } = string.Empty;
            public string Elevation { get; set; } = string.Empty;
            public string Latitude { get; set; } = string.Empty;
            public string Longitude { get; set; } = string.Empty;
            public string Station { get; set; } = string.Empty;
            public string Offset { get; set; } = string.Empty;
            public string ProfileElevation { get; set; } = string.Empty;
            public string ProfileSlope { get; set; } = string.Empty;
            public string TerrainElevation { get; set; } = string.Empty;
            public string TerrainSlope { get; set; } = string.Empty;
            #endregion

            #region Constructors
            public DataPoint(DPoint3d uorPoint, BaseGCS projection, Alignment alignment, TerrainSurface surface)
            {
                DgnModel model = Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModel();
                Bentley.DgnPlatformNET.DistanceFormatter distanceFormatter = new DistanceFormatter(model);
                Bentley.DgnPlatformNET.AngleFormatter angleFormatter = new AngleFormatter(model);
                angleFormatter.AngleMode = AngleMode.DegMinSec;
                angleFormatter.AnglePrecision = AnglePrecision.Use5Places;

                ModelInfo info = model.GetModelInfo();
                double UORTOMETER = 1.0 / info.UorPerMeter;


                double x = UORTOMETER * uorPoint.X;
                double y = UORTOMETER * uorPoint.Y;
                double z = UORTOMETER * uorPoint.Z;
                if (!model.Is3d)
                    z = 0;

                DPoint3d metricPoint = new DPoint3d(x, y, z);

                this.SetCoordinateStrings(uorPoint, distanceFormatter, model);
                this.SetProjectionStrings(projection, metricPoint, angleFormatter);
                this.SetAlignmentStrings(alignment, metricPoint);
                this.SetTerrainStrings(surface, metricPoint);
            }
            #endregion

            #region Set Strings
            private void SetCoordinateStrings(DPoint3d uorPoint, DistanceFormatter f, DgnModel model)
            {
                this.East = f.ToString(uorPoint.X);
                this.North = f.ToString(uorPoint.Y);
                if (model.Is3d)
                    this.Elevation = f.ToString(uorPoint.Z);
            }

            private void SetProjectionStrings(BaseGCS projection, DPoint3d metricPoint, AngleFormatter formatter)
            {
                if (projection != null)
                {
                    GeoPoint latlon;
                    int status = projection.LatLongFromCartesian(out latlon, ref metricPoint);
                    if (status == 0)
                    {
                        string ns = (latlon.Latitude >= 0) ? "N:" : "S:";
                        this.Latitude = ns + formatter.ToString(Math.Abs(latlon.Latitude));

                        string ew = (latlon.Longitude >= 0) ? "E:" : "W:";
                        this.Longitude = ew + formatter.ToString(Math.Abs(latlon.Longitude));
                    }
                }
            }

            private void SetAlignmentStrings(Alignment alignment, DPoint3d metricPoint)
            {
                if (alignment != null)
                {
                    DgnModel model = Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModel();
                    LinearPoint lp = alignment.LinearGeometry.ProjectPointOnPerpendicular(metricPoint);
                    if (lp != null)
                    {
                        LinearPoint stationPoint = alignment.LinearGeometry.ProjectPointOnPerpendicular(metricPoint);

                        // Get numerical station
                        string stationStr = "";
                        double stationNum = stationPoint.DistanceOnExtension + stationPoint.DistanceAlong;

                        // Format it
                        StationingFormatter sformatter = new StationingFormatter(alignment);
                        StationFormatSettings settings = StationFormatSettings.GetStationFormatSettingsForModel(model);
                        sformatter.FormatStation(ref stationStr, stationNum, settings);
                        this.Station = stationStr;

                        string rl = (lp.Offset > 0) ? " RT" : " LT";
                        if (Math.Abs(lp.Offset) < 0.000001)
                            rl = "";
                        this.Offset = FormatForDisplay.Distance(lp.Offset, model, 3) + rl;

                        Profile pr = alignment.ActiveProfile;
                        if (pr != null)
                        {
                            LinearPoint pp = pr.ProfileGeometry.GetPointAtX(lp.DistanceAlong);
                            if (pp != null)
                            {
                                this.ProfileElevation = FormatForDisplay.Distance(pp.Coordinates.Y, model, 3);

                                this.ProfileSlope = FormatForDisplay.Double(pr.ProfileGeometry.GetSlopeAtX(lp.DistanceAlong)) + "%";
                            }
                        }
                    }
                }
            }

            private void SetTerrainStrings(TerrainSurface surface, DPoint3d metricPoint)
            {
                if (surface != null)
                {
                    Bentley.TerrainModelNET.DTMDrapedPoint dp = surface.DTM?.DrapePoint(metricPoint);
                    if (dp != null && Math.Abs(dp.Coordinates.Z) > 0.001)
                    {
                        DgnModel model = Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModel();
                        this.TerrainElevation = FormatForDisplay.Distance(dp.Coordinates.Z, model, 3);
                        this.TerrainSlope = FormatForDisplay.Double(dp.Slope) + "%";

                    }
                }
            }
            #endregion

            #region Get Strings
            private void AddNameValue(string name, string value, ref List<string> names, ref List<string> values, bool always = false)
            {
                if (!string.IsNullOrWhiteSpace(value) || always)
                {
                    names.Add(name);
                    values.Add(value);
                }
            }

            public void GetStringLists(ref List<string> names, ref List<string> values, bool isProjectionValid, bool isAlignmentValid, bool isSurfaceValid, bool always = false)
            {
                this.AddNameValue("X East", this.East, ref names, ref values, always);
                this.AddNameValue("Y North", this.North, ref names, ref values, always);
                this.AddNameValue("Z Elevation", this.Elevation, ref names, ref values, always);

                if (isProjectionValid)
                {
                    this.AddNameValue("Latitude", this.Latitude, ref names, ref values, always);
                    this.AddNameValue("Longitude", this.Longitude, ref names, ref values, always);
                }
                if (isAlignmentValid)
                {
                    this.AddNameValue("Station", this.Station, ref names, ref values, always);
                    this.AddNameValue("Offset", this.Offset, ref names, ref values, always);
                    this.AddNameValue("Profile Elevation", this.ProfileElevation, ref names, ref values, always);
                    this.AddNameValue("Profile Slope", this.ProfileSlope, ref names, ref values, always);
                }
                if (isSurfaceValid)
                {
                    this.AddNameValue("Terrain Elevation", this.TerrainElevation, ref names, ref values, always);
                    this.AddNameValue("Terrain Slope", this.TerrainSlope, ref names, ref values, always);
                }
            }
            #endregion

        }
    }